iT邦幫忙

2024 iThome 鐵人賽

DAY 14
0
自我挑戰組

30 天 Node.js 探索:基礎、進階與實踐系列 第 14

Day 14:驗證與授權:JWT (JSON Web Token) 簡介

  • 分享至 

  • xImage
  •  

接下來要學習如何使用 JWT (JSON Web Token) 進行使用者身份驗證與授權,並且了解它的運作原理。

什麼是 JWT?

JWT (JSON Web Token) 是基於JSON object的編碼,並透過這個編碼進行傳遞資訊。用於在應用程式中傳遞使用者的驗證訊息。JWT 通常用來處理身份驗證和授權,通過加密簽名保護資料的完整性,並以輕量化的方式傳遞資訊。

JWT 結構:

JWT 由三部分構成,使用「.」分隔:

  • Header(標頭): 包含令牌類型(通常是 JWT)與簽名演算法(如 HS256)。
  • Payload(有效載荷): 儲存使用者訊息及聲明(Claims),例如 id、username 等。
  • Signature(簽名): 對前兩部分進行加密,防止資料被篡改。

JWT 的運作流程

JWT 通常應用在 身份驗證 系統中,基本上的流程會像下面這樣:

  • 登入: 使用者向伺服器發送登入請求,並提供憑證(例如用戶名和密碼)。
  • 生成 JWT: 伺服器驗證使用者憑證,如果驗證成功,伺服器會生成一個 JWT,並將其返回給使用者。
  • 存儲 JWT: 使用者將 JWT 儲存於 localStorage 或 cookies 中,以便於後續請求使用。
  • 授權請求: 使用者每次發送 API 請求時,將 JWT 包含在請求頭中。伺服器驗證該 JWT,如果合法則允許訪問資源。

安裝所需的套件

首先需要安裝一些套件來生成和驗證 JWT:

bash
npm install jsonwebtoken bcryptjs
  • jsonwebtoken: 生成和解析 JWT 的核心套件。
  • bcryptjs: 用於加密和比對密碼的工具。

JWT 驗證實作

接著要使用 Express 來建立一個簡單的登入系統,並透過 JWT 進行身份驗證。
設定 Express 應用與使用者模型:

js
const express = require('express');
const jwt = require('jsonwebtoken');
const bcrypt = require('bcryptjs');

const app = express();
app.use(express.json());

const users = []; // 模擬的使用者資料庫

// 假設密鑰 (注意:在實際應用中應該要儲存在環境變數中)
const jwtSecret = 'supersecretkey';

用戶註冊與加密密碼:

js
app.post('/register', async (req, res) => {
  const { username, password } = req.body;

  // 加密密碼
  const hashedPassword = await bcrypt.hash(password, 10);

  // 儲存使用者
  users.push({ username, password: hashedPassword });
  res.status(201).send('User registered');
});

登入與生成 JWT:

js
app.post('/login', async (req, res) => {
  const { username, password } = req.body;

  // 檢查使用者是否存在
  const user = users.find(u => u.username === username);
  if (!user) {
    return res.status(400).send('User not found');
  }

  // 檢查密碼是否正確
  const isPasswordValid = await bcrypt.compare(password, user.password);
  if (!isPasswordValid) {
    return res.status(401).send('Invalid password');
  }

  // 生成 JWT
  const token = jwt.sign({ username: user.username }, jwtSecret, { expiresIn: '1h' });
  res.json({ token });
});

保護路由(授權):

js
function authenticateToken(req, res, next) {
  const token = req.headers['authorization']?.split(' ')[1];

  if (!token) {
    return res.status(401).send('Access denied');
  }

  // 驗證 JWT
  jwt.verify(token, jwtSecret, (err, user) => {
    if (err) {
      return res.status(403).send('Invalid token');
    }
    req.user = user;
    next();
  });
}

app.get('/protected', authenticateToken, (req, res) => {
  res.send(`Hello, ${req.user.username}, you are authorized!`);
});

在這裡定義了一個 authenticateToken 中介軟體,用來解析和驗證 JWT,只有攜帶合法令牌的請求才能進入 protected 路由。

驗證與授權的區別

  • 驗證(Authentication): 確認使用者的身份是否真實。像是登入過程中驗證用戶名與密碼是否正確。
  • 授權(Authorization): 確認已驗證的使用者是否有權限存取特定資源。像是只有擁有特定角色的使用者可以訪問某些 API。

JWT 的安全性考量

  • 保持密鑰安全: JWT 的安全性依賴於加密簽名,因此要確保密鑰不被洩漏,建議使用環境變數來存儲。
  • 設置過期時間: 為了防止令牌長時間暴露,應設置合理的過期時間,通常是一小時或更短。
  • **HTTPS: **確保應用程序在 HTTPS 下運行,以防止 JWT 被中間人攻擊截取。

總結

今天學習了 JWT 的基本概念以及它在驗證和授權中的應用。實作了簡單的使用者登入系統,使用 JWT 生成、驗證令牌,並且保護了敏感的 API 路由。JWT 可以在無狀態的應用程式中實現有效的身份驗證,在後續的應用開發中,這是建立安全系統的關鍵技術。


上一篇
Day 13: 資料庫操作與 CRUD
下一篇
Day 15: 錯誤處理與日誌管理
系列文
30 天 Node.js 探索:基礎、進階與實踐26
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言